#include "autoupdate.h"
#include "./ui_autoupdate.h"

#include "QtGui/private/qzipreader_p.h"
//#include "QtGui/private/qzipwriter_p.h"
#include "Format.h"
#include <QThread>

AutoUpdate::AutoUpdate(QWidget *parent)
    : QDialog(parent)
    , ui(new Ui::AutoUpdate)
{
    ui->setupUi(this);

}

AutoUpdate::~AutoUpdate()
{
    delete ui;
}

void AutoUpdate::initAutoUpdate(QStringList args)
{
    //    m_curVerison = "1.0.1";
    //    m_strRemoteUrl ="http://10.35.19.63:8091/autoupdate/autoupdate.json";
    //    m_exeFileName ="HaloKpy.exe";
    m_curVerison = args.at(1);
    m_exeFileName =args.at(2);
    m_strRemoteUrl =args.at(3);
    qDebug()<<"入参"<<m_curVerison<<m_exeFileName<<m_strRemoteUrl;
    m_bIsFinished = false;
    ui->progressBar->setValue(0);
    //setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowStaysOnTopHint);
    getAutoUpdateJsonFile();
}

void AutoUpdate::getAutoUpdateJsonFile()//读取远程更新文件
{
    m_netManager = new QNetworkAccessManager(this);          //新建QNetworkAccessManager对象
    connect(m_netManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));//关联信号和槽

    qDebug()<<"获取远程配置文件"<<m_strRemoteUrl;
    QNetworkRequest quest;
    quest.setUrl(QUrl(m_strRemoteUrl)); //包含最新版本软件的下载地址
    quest.setHeader(QNetworkRequest::UserAgentHeader, "RT-Thread ART");
    m_pReply = m_netManager->get(quest);    //发送get网络请求
    connect(m_pReply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)),this, SLOT(slotError()));
    connect(m_pReply, SIGNAL(sslErrors(QList<QSslError>)),this, SLOT(slotSslErrors(QList<QSslError>)));
}

void AutoUpdate::slotError()
{
    qDebug() << "slotError";
    m_netManager->deleteLater();
    m_pReply->deleteLater();
    m_pReply=NULL;
}

void AutoUpdate::slotSslErrors(QList<QSslError>)
{
    qDebug() << "slotSslErrors";
    m_netManager->deleteLater();
    m_pReply->deleteLater();
    m_pReply=NULL;
}

void AutoUpdate::replyFinished(QNetworkReply *reply)
{
    QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if (statusCode != 200)
    {
        QMessageBox::critical(this, QString::fromLocal8Bit("Json文件下载失败 状态码:%1").arg(statusCode.toString()), reply->errorString());
        return;
    }

    ParseJson(reply->readAll());
    m_netManager->deleteLater();
    reply->deleteLater();
    reply=NULL;
}

bool AutoUpdate::ParseJson(const QString &str)
{
    QJsonParseError err_rpt;
    QJsonDocument  root_Doc = QJsonDocument::fromJson(str.toUtf8(), &err_rpt);//字符串格式化为JSON

    if (err_rpt.error != QJsonParseError::NoError)
    {
        QMessageBox::critical(this, QString::fromLocal8Bit("检查失败"), QString::fromLocal8Bit("服务器地址错误或JSON格式错误!"));
        return false;
    }
    if (root_Doc.isObject())
    {
        QJsonObject  root_Obj = root_Doc.object();   //创建JSON对象，不是字符串
        //QStringList keys = root_Obj.keys();

        m_lastVerison = root_Obj.value("LatestVerison").toString();  //V1.0
        m_updateTime = root_Obj.value("UpdateTime").toString();
        m_releaseNote = root_Obj.value("ReleaseNote").toString();
        m_urlZipFiles.setUrl(root_Obj.value("ZipUpdateFiles").toString());
        qDebug()<<"获取远程版本信息"<<m_lastVerison<<m_updateTime<<m_releaseNote<<m_urlZipFiles;

        if (m_lastVerison > m_curVerison)
        {
            this->show();
            QString warningStr = "当前版本【"+m_curVerison+"】检测到新版本!\n\n版本号：" + m_lastVerison + "\n" + "更新时间：" + m_updateTime + "\n" + "更新说明：" + m_releaseNote;
            ui->textBrowser->setText(warningStr);
        }
        else
        {
            QMessageBox::information(this, "提示","当前已是最新版本【"+m_curVerison+"】！");
            this->close();
            //ExitApp(QCoreApplication::applicationFilePath());
        }
    }
    return true;
}

void AutoUpdate::on_btnCancel_clicked()
{
//    //解压覆盖更新文件
//    QString strExePath = QCoreApplication::applicationDirPath();//获取应用程序可执行文件所在的目录
//    m_strFileName =  "D:/sourcetree/auto-update/build/Release/downtemp/autoupdate.zip";
//    QZipReader reader(m_strFileName);
//    bool  ret =reader.extractAll(strExePath);
//    if (!ret) {
//        qDebug() << "Extract failed: " << reader.status();
//    } else {
//        qDebug() << "Extract successful.";
//    }
//    reader.close();
//    qDebug()<<"解压更新包到:"<<strExePath<<m_strFileName<<ret;
    qApp->exit(0);
}

void AutoUpdate::on_btnUpdate_clicked()
{
    ui->btnCancel->setEnabled(false);

    if(!m_bIsFinished){
        DownLoadUpdateFiles();
        ui->btnUpdate->setEnabled(false);
    }
    else{
        QString strExePath = QCoreApplication::applicationDirPath();//获取应用程序可执行文件所在的目录
        //关闭旧程序
        QStringList args;
        args << "/F"<<"/IM"<< m_exeFileName;
        qDebug()<<"关闭旧程序:"<<m_exeFileName;
        QProcess::execute("taskkill", args);
        QThread::sleep(2);
        //删除文件
        QString filePath = strExePath+"/"+m_exeFileName;
        QFile file(filePath);
        file.remove();
        qDebug()<<"删除文件"<<filePath;
        //解压覆盖更新文件

        QZipReader reader(m_strFileName);
        bool  ret =reader.extractAll(strExePath);
        if (!ret) {
            qDebug() << "Extract failed: " << reader.status();
        } else {
            qDebug() << "Extract successful.";
        }
        reader.close();
        qDebug()<<"解压更新包到:"<<strExePath<<m_strFileName<<ret;
        //重启程序
        QString strExeFile = strExePath +"/"+m_exeFileName;
        qDebug()<<"重启新程序:"<<strExeFile;
        QProcess::startDetached(strExeFile);
        this->close();
    }
}

void AutoUpdate::DownLoadUpdateFiles()
{
    /**放置下载的文件的路径**/
    QString strCurrentDir = QCoreApplication::applicationDirPath();//当前程序运行路径
    QString strPlaceDir = strCurrentDir + "/downtemp/";
    QDir directory(strPlaceDir);//如果路径不存在，则创建
    if (!directory.exists())
        directory.mkpath(strPlaceDir);

    QFileInfo fileInfo(m_urlZipFiles.path());
    m_zipFiles = fileInfo.fileName();

    m_strFileName = strPlaceDir + m_zipFiles;

    if (QFile::exists(m_strFileName))//如果文件已经存在，那么删除
        QFile::remove(m_strFileName);

    m_file = new QFile(m_strFileName);
    if (!m_file->open(QIODevice::WriteOnly | QIODevice::Text))
    {
        m_file->close();
        delete m_file;
        m_file = NULL;
        return;
    }

    if (m_urlZipFiles.isEmpty())
    {

        return;
    }
    ui->updateStatus->setText("开始下载更新文件...");
    //m_strTip = QString::fromLocal8Bit("开始下载更新文件...");

    m_bIsFinished = false;
    m_netManagerDown = new QNetworkAccessManager(this);
    QNetworkRequest request(m_urlZipFiles);
    request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy);
    //request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
    m_pReply = m_netManagerDown->get(request);

    connect(m_pReply, SIGNAL(readyRead()), this, SLOT(ReplyNewDataArrived()));//当有新数据到达时就会触发此信号
    connect(m_pReply, SIGNAL(finished()), this, SLOT(ReplyHttpFinished()));//完成数据接收后发送此信号
    connect(m_pReply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(ReplyError()));//出现错误时发送此信号;
    connect(m_pReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(onDownloadProgress(qint64, qint64)));//用来提示文件下载进度
    m_downloadTime.start();
    qDebug()<<"下载最新版本压缩包到:"<<strPlaceDir;
}

void AutoUpdate::ReplyNewDataArrived()//响应m_netReply有新的数据到达
{
    ui->updateStatus->setText("正在下载更新文件...");
    if (m_file)
    {
        // 写文件-形式为追加
        QFile file(m_strFileName);
        if (file.open(QIODevice::Append))
            file.write(m_pReply->readAll());
        file.close();
    }
    else
    {
        qDebug() << m_pReply->readAll();
    }
}

void AutoUpdate::ReplyHttpFinished()
{
    ui->updateStatus->setText("更新完成！");
    m_bIsFinished = true;
    m_netManagerDown->deleteLater();
    m_pReply->deleteLater();
    m_file->close();
    m_file->deleteLater();
    ui->btnUpdate->setEnabled(true);
    ui->btnUpdate->setText("重启");

    //qDebug() << "ReplyFinished";

}

void AutoUpdate::ReplyError()
{
    qDebug() << "ReplyError";
    m_netManagerDown->deleteLater();
    m_pReply->deleteLater();
    m_file->close();
    m_file->deleteLater();
    m_pReply=NULL;
}


void AutoUpdate::onDownloadProgress( qint64 bytesReceived, qint64 bytesTotal)
{
    ui->lblFileInfo->setText(m_zipFiles);
    // 总时间
    int nTime = m_downloadTime.elapsed();

    // 本次下载所用时间
    nTime -= m_nTime;

    // 下载速度
    double dBytesSpeed = (bytesReceived * 1000.0) / nTime;
    double dSpeed = dBytesSpeed;

    //剩余时间
    qint64 leftBytes = (bytesTotal - bytesReceived);
    double dLeftTime = (leftBytes * 1.0) / dBytesSpeed;

    ui->lblSpeedInfo->setText(speed(dSpeed));
    ui->lblLeftTime->setText(timeFormat(dLeftTime));
    ui->lblFileInfoSize->setText(formatSize(bytesTotal));
    ui->lblDownLoadInfo->setText(formatSize(bytesReceived));
    ui->progressBar->setMaximum(bytesTotal);
    ui->progressBar->setValue(bytesReceived);

    // 获取上一次的时间
    m_nTime = nTime;
}



